package com.y.report.controller;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.y.report.entity.common.R;
import com.y.report.hepler.DbHelper;
import com.y.report.hepler.JdbcDriverLoaderHepler;
import com.y.report.hepler.ResultSetUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.LongStream;

@Controller
@Slf4j
public class EntryContrller {

    private static final Map<String, List<Map<String, Object>>> datas = new LinkedHashMap<>();

    private static final int DEFAULT_RANDOM_RANGE = 65535;
    private static final String DEFAULT_SESSION_HEADER_KEY = "session_id";
    private static final String DEFAULT_SESSION_HEADER_VALUE = "default_session_id";

    @Autowired
    private HttpServletRequest request;

    @RequestMapping(value = "/entry", method = RequestMethod.POST)
    public @ResponseBody
    R entry(@RequestBody(required = false) Map<String, Object> body, @RequestHeader(value = DEFAULT_SESSION_HEADER_KEY, defaultValue = DEFAULT_SESSION_HEADER_VALUE) String sessoinId) {
        final Integer pageIndex = MapUtil.getInt(body, "page_index", 1);
        final Integer pageSize = MapUtil.getInt(body, "page_size", 10);
        final long sleepMs = MapUtil.getLong(body, "sleepMs", -1L);
        final int pageStartOffset = PageUtil.getStart(pageIndex - 1, pageSize);
        log.info("query page, sleepMs:{}, sessionId:{}, body:{}", sleepMs, sessoinId, JSONUtil.toJsonPrettyStr(body));
        if (sleepMs > 0L) {
            try {
                log.info("sleepMs", sessoinId, JSONUtil.toJsonPrettyStr(body));
                TimeUnit.MILLISECONDS.sleep(sleepMs);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        return R.success(datas.getOrDefault(sessoinId, dataInit(null, sessoinId))
                .stream()
                .skip(pageStartOffset)
                .limit(pageSize)
                .collect(Collectors.toList())
        );
    }

    @RequestMapping(path = "/entry/cnt", method = RequestMethod.POST)
    public @ResponseBody
    R entryCnt(
            @RequestParam(required = false, name = "total_count") Integer totalCount,
            @RequestBody(required = false) Map<String, Object> body, @RequestHeader(value = DEFAULT_SESSION_HEADER_KEY, defaultValue = DEFAULT_SESSION_HEADER_VALUE) String sessoinId
    ) {
        List<Map<String, Object>> data = datas.getOrDefault(sessoinId, Collections.emptyList());
        if (Objects.nonNull(totalCount) && data.size() < totalCount) {
            dataInit(null, sessoinId);
        }

        //final int totalCount = dataList.size();
        final int pageSize = MapUtil.getInt(body, "page_size", 10);
        final long sleepMs = MapUtil.getLong(body, "sleepMs", -1L);
        final int totalPage = PageUtil.totalPage(totalCount, pageSize);
        log.info("query page, sleepMs:{}, sessionId:{}, totalCount:{}", sleepMs, sessoinId, totalCount);
        if (sleepMs > 0L) {
            try {
                log.info("sleepMs", sessoinId, JSONUtil.toJsonPrettyStr(body));
                TimeUnit.MILLISECONDS.sleep(sleepMs);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        return R.success(MapUtil.builder()
                .put("totalCount", totalCount)
                .put("totalPage", totalPage)
                .put("pageSize", pageSize)
                .build()
        );
    }

    @RequestMapping(path = "/entry/clean", method = RequestMethod.POST)
    public @ResponseBody
    R entryCnt(
            @RequestBody Map<String, Object> body, @RequestHeader(value = DEFAULT_SESSION_HEADER_KEY, defaultValue = DEFAULT_SESSION_HEADER_VALUE) String sessoinId
    ) {
        if (StringUtils.equals(sessoinId, DEFAULT_SESSION_HEADER_VALUE)) {
            datas.clear();
        } else {
            datas.getOrDefault(sessoinId, Collections.emptyList()).clear();
        }
        log.info("query page, sessionId:{}", sessoinId);
        return R.ok();
    }

    private List<Map<String, Object>> dataInit(Integer totalCount, String sessionId) {
        if (totalCount == null)
            totalCount = RandomUtil.randomInt(DEFAULT_RANDOM_RANGE);
        datas.getOrDefault(sessionId, Collections.emptyList()).clear();
        List<Map<String, Object>> dataList = LongStream.range(0, totalCount)
                .mapToObj(x -> {
                    final Map<String, Object> data = new LinkedHashMap<>();
                    final int intMaxLen = 65535;
                    final int strMaxLen = 7;
                    //data.put("id", RandomUtil.randomInt(intLen));
                    data.put("id", x + 1);
                    data.put("test_type", RandomUtil.randomString(strMaxLen));
                    data.put("test_name", RandomUtil.randomString(strMaxLen));
                    data.put("test_desc", RandomUtil.randomString(strMaxLen));
                    data.put("current_cnt", RandomUtil.randomInt(intMaxLen));
                    data.put("total_cnt", RandomUtil.randomInt(intMaxLen));
                    data.put("begin_time", DateUtil.formatDateTime(RandomUtil.randomDate(DateUtil.date(), DateField.DAY_OF_MONTH, 1, 30)));
                    data.put("end_time", DateUtil.formatDateTime(RandomUtil.randomDate(DateUtil.date(), DateField.DAY_OF_MONTH, 1, 30)));
                    data.put("elapsed_ms", RandomUtil.randomDouble());
                    data.put("time_consuming_details", RandomUtil.randomString(strMaxLen));
                    data.put("suss_cnt", RandomUtil.randomInt(intMaxLen));
                    data.put("speed", RandomUtil.randomDouble());
                    data.put("speed_unit", RandomUtil.randomString(strMaxLen));
                    data.put("mark", RandomUtil.randomString(strMaxLen));
                    data.put("batch_number", RandomUtil.randomString(strMaxLen));
                    data.put("upsert_time", DateUtil.formatDateTime(RandomUtil.randomDate(DateUtil.date(), DateField.DAY_OF_MONTH, 1, 30)));
                    data.put("test", RandomUtil.randomInt());
                    return data;
                }).collect(Collectors.toList());
        datas.put(sessionId, dataList);
        return dataList;
    }

    /*

curl http://192.168.113.247:10001/y/testApi \
-X POST -v -L \
-u root:Web@2022.ztn \
-H "label:$__label" \
-H "strict_mode:true" \
-H "format: csv" \
-H "column_separator:|" \
-H 'Content-Type: application/json' \
-d 'aaa'
     */
    @RequestMapping(path = "/testApi")
    public @ResponseBody
    R testApi(HttpServletRequest request) throws Exception {
        log.info("request -> url:{}, uri:{}, method:{} ", request.getRequestURL(), request.getRequestURI(), request.getMethod());
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            log.info("headers -> headerName:{}, headerValue:{} ", headerName, headerValue);
        }
        if (Objects.nonNull(request.getCookies()))
            for (Cookie cookie : request.getCookies()) {
                log.info("cookies -> cookie:{}", JSON.toJSONString(cookie));
            }
        if (Objects.nonNull(request.getParameterMap()))
            for (Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
                log.info("params -> key:{}, value:{}", entry.getKey(), entry.getValue());
            }
        try (ServletInputStream sis = request.getInputStream();
             ByteArrayOutputStream baos = new ByteArrayOutputStream();) {
            byte[] buf = new byte[1024];
            int len;
            while ((len = sis.read(buf)) != -1) {
                baos.write(buf, 0, len);
            }
            String body = new String(baos.toByteArray(), StandardCharsets.UTF_8);
            log.info("body -> content:{}", body);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }

        return R.success(datas.entrySet().stream()
                .map(x -> x.getValue())
                .skip(0)
                .limit(10)
                .collect(Collectors.toList())
        );
    }

    public static void testQ(String sss) {
        try {
            Class.forName("io.trino.jdbc.TrinoDriver");
            Connection conn = DriverManager.getConnection("jdbc:trino://10.192.112.69:18091", "zt17606", null);
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery("select now(),version()");
            List<Map<String, Object>> list = ResultSetUtil.getList(rs);
            rs.close();
            stmt.close();
            conn.close();
            System.out.println(sss + " 22222result:" + list);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
